import { BaseElement, Element, ParentElement, RequestLayoutState, PrepaintState, PaintContext } from './element'
import { withStyled, Styled } from './styled'
import { ScrollHandle } from './scroll'

/**
 * Div元素的布局请求状态
 */
export interface DivRequestLayoutState extends RequestLayoutState {
  children?: RequestLayoutState[]
}

/**
 * Div元素的预绘制状态
 */
export interface DivPrepaintState extends PrepaintState {
  children?: PrepaintState[]
}

/**
 * 样式属性
 */
export interface StyleProps {
  [key: string]: string | number | boolean | undefined
}

/**
 * 交互元素状态
 */
export interface InteractiveElementState {
  focused: boolean
  clicked: boolean
  hovered: boolean
  scrolled?: boolean
}

/**
 * 事件回调
 */
export type EventCallback<T extends Event> = (event: T) => void

/**
 * Div元素类，作为GPUI树的核心容器
 */
export class Div extends BaseElement implements ParentElement<Element> {
  private _children: Element[] = []
  private style: StyleProps = {}
  private state: InteractiveElementState = {
    focused: false,
    clicked: false,
    hovered: false
  }
  private eventHandlers: Map<string, EventCallback<any>[]> = new Map()
  private tagName: string = 'div'
  private attributes: Map<string, string> = new Map()
  private innerText: string = ''
  private scrollHandle: ScrollHandle | null = null
  // @ts-ignore: 这些属性用于存储状态，当前仅设置未读取
  private _overflowX: 'visible' | 'hidden' | 'scroll' | 'auto' = 'visible'
  // @ts-ignore: 这些属性用于存储状态，当前仅设置未读取
  private _overflowY: 'visible' | 'hidden' | 'scroll' | 'auto' = 'visible'
  // @ts-ignore: 这些属性用于存储状态，当前仅设置未读取
  private _allowConcurrentScroll: boolean = false
  // @ts-ignore: 这些属性用于存储状态，当前仅设置未读取
  private _restrictScrollToAxis: boolean = false

  /**
   * 添加子元素
   */
  addChild(child: Element): void {
    this._children.push(child)
  }

  /**
   * 设置溢出行为
   */
  setOverflow(x: 'visible' | 'hidden' | 'scroll' | 'auto', y: 'visible' | 'hidden' | 'scroll' | 'auto'): this {
    this._overflowX = x
    this._overflowY = y
    this.setStyle({ overflowX: x, overflowY: y })
    return this
  }

  /**
   * 获取或创建滚动句柄
   */
  getScrollHandle(): ScrollHandle | null {
    if (!this.scrollHandle) {
      this.scrollHandle = new ScrollHandle()
    }
    return this.scrollHandle
  }

  /**
   * 设置滚动相关的选项
   */
  setScrollOptions(options: {
    allowConcurrentScroll?: boolean
    restrictScrollToAxis?: boolean
  }): this {
    if (options.allowConcurrentScroll !== undefined) {
      this._allowConcurrentScroll = options.allowConcurrentScroll
    }
    if (options.restrictScrollToAxis !== undefined) {
      this._restrictScrollToAxis = options.restrictScrollToAxis
    }
    return this
  }

  /**
   * 添加子元素并返回this，支持链式调用
   */
  child(child: Element | string): this {
    if (typeof child === 'string') {
      // 如果是字符串，创建一个文本元素
      const textElement = new Div()
      textElement.setText(child)
      this.addChild(textElement)
    } else {
      this.addChild(child)
    }
    return this
  }

  /**
   * 移除子元素
   */
  removeChild(child: Element): void {
    const index = this._children.findIndex(c => c.id().toString() === child.id().toString())
    if (index !== -1) {
      this._children.splice(index, 1)
    }
  }

  /**
   * 获取所有子元素
   */
  children(): ReadonlyArray<Element> {
    return this._children
  }

  /**
   * 设置样式
   */
  setStyle(style: StyleProps): this {
    this.style = { ...this.style, ...style }
    return this
  }

  /**
   * 设置标签名
   */
  setTagName(tagName: string): this {
    this.tagName = tagName
    return this
  }

  /**
   * 设置属性
   */
  setAttribute(name: string, value: string): this {
    this.attributes.set(name, value)
    return this
  }

  /**
   * 设置文本内容
   */
  setText(text: string): this {
    this.innerText = text
    return this
  }

  /**
   * 请求布局
   */
  requestLayout(state: DivRequestLayoutState): void {
    if (state.needsLayout) {
      // 处理布局请求逻辑
    }
  }

  /**
   * 预绘制
   */
  prepaint(_state: DivPrepaintState): void {
    // 处理预绘制逻辑
  }

  /**
   * 滚动到指定位置
   */
  scrollTo(x: number, y: number): this {
    const handle = this.getScrollHandle()
    if (handle) {
      handle.setOffset(x, y)
      this.state.scrolled = true
      // 在实际实现中，这里应该触发重绘
    }
    return this
  }

  /**
   * 滚动到指定子元素
   */
  scrollToItem(index: number): this {
    const handle = this.getScrollHandle()
    if (handle) {
      handle.scrollToItem(index)
      this.state.scrolled = true
      // 在实际实现中，这里应该触发重绘
    }
    return this
  }

  /**
   * 滚动到底部
   */
  scrollToBottom(): this {
    const handle = this.getScrollHandle()
    if (handle) {
      handle.scrollToBottom()
      this.state.scrolled = true
      // 在实际实现中，这里应该触发重绘
    }
    return this
  }

  /**
   * 绘制
   */
  paint(context: PaintContext): HTMLElement {
    // 检查是否有Scene，如果有，绘制到Scene
    if (context.scene) {
      // 从样式中提取尺寸信息，如果没有则使用默认值
      const getSizeValue = (value: any, defaultValue: number) => {
        if (typeof value === 'number') return value;
        if (typeof value === 'string') {
          const num = parseInt(value);
          return isNaN(num) ? defaultValue : num;
        }
        return defaultValue;
      };
      
      const width = getSizeValue(this.style.width, 100);
      const height = getSizeValue(this.style.height, 100);
      
      // 创建矩形图元表示div
      const rect = context.scene.createRect(
        this.id().toString(),
        {
          x: 0,
          y: 0,
          width: width,
          height: height
        },
        this.style
      )

      // 如果有文本内容，创建文本图元
      if (this.innerText) {
        const text = context.scene.createText(
          `${this.id().toString()}-text`,
          {
            x: 0,
            y: 0,
            width: width,
            height: height
          },
          this.innerText,
          this.style
        )
        // 将文本图元添加为矩形图元的子元素，而不是直接插入场景
        if (!rect.children) {
          rect.children = []
        }
        rect.children.push(text)
      }

      // 插入矩形图元到场景
      context.scene.insertPrimitive(rect)

      // 递归绘制子元素
      this._children.forEach(child => {
        const childElement = child.paint(context)
        // 将子元素添加到父元素中
        if (rect.children) {
          // 对于文本子元素，我们需要特殊处理
          if (typeof child === 'object' && 'innerText' in child && (child as any).innerText) {
            const text = context.scene.createText(
              `${child.id().toString()}-text`,
              {
                x: 0,
                y: 0,
                width: width,
                height: height
              },
              (child as any).innerText,
              this.style
            )
            rect.children.push(text)
          } else {
            // 对于其他类型的子元素，我们直接使用其绘制结果
            // 这里我们需要获取子元素的图元表示
            const childPrimitive = childElement as any
            if (childPrimitive && childPrimitive.id) {
              // 创建一个子图元并添加到父图元的children数组
              const childRect = context.scene.createRect(
                childPrimitive.id,
                {
                  x: 0,
                  y: 0,
                  width: width,
                  height: height
                },
                this.style
              )
              rect.children.push(childRect)
            }
          }
        }
      })
    }

    // 为了保持兼容性，仍然返回一个DOM元素
    const element = document.createElement(this.tagName)
    element.id = this.id().toString()

    // 设置样式
    Object.entries(this.style).forEach(([key, value]) => {
      if (value !== undefined) {
        element.style[key as any] = value.toString()
      }
    })

    // 设置属性
    this.attributes.forEach((value, key) => {
      element.setAttribute(key, value)
    })

    // 设置文本
    if (this.innerText) {
      element.innerText = this.innerText
    }

    // 处理滚动逻辑
    if (this.scrollHandle) {
      // 获取当前滚动偏移量
      const { x, y } = this.scrollHandle.offset
      
      // 创建一个包装元素来应用滚动偏移
      const scrollContainer = document.createElement('div')
      scrollContainer.style.position = 'relative'
      scrollContainer.style.transform = `translate(${-x}px, ${-y}px)`
      
      // 绘制子元素到滚动容器中
      this._children.forEach(child => {
        if (child.render) {
          const childElement = child.render()
          scrollContainer.appendChild(childElement)
        }
      })
      
      element.appendChild(scrollContainer)
      
      // 添加滚动事件监听
      const handleScroll = (e: Event) => {
        const target = e.target as HTMLElement
        const newX = target.scrollLeft
        const newY = target.scrollTop
        this.scrollHandle?.setOffset(newX, newY)
        this.state.scrolled = true
      }
      
      element.addEventListener('scroll', handleScroll)
      
      // 存储事件处理函数以便后续清理
      const handlers = this.eventHandlers.get('scroll') || []
      handlers.push(handleScroll as EventCallback<Event>)
      this.eventHandlers.set('scroll', handlers)
    } else {
      // 添加子元素
      this._children.forEach(child => {
        if (child.render) {
          const childElement = child.render()
          element.appendChild(childElement)
        }
      })
    }

    // 绑定事件处理程序
    this.bindEvents(element)

    return element
  }

  /**
   * 绑定事件处理程序
   */
  private bindEvents(element: HTMLElement): void {

    this.eventHandlers.forEach((handlers, eventType) => {
      handlers.forEach(handler => {
        element.addEventListener(eventType, handler)
      })
    })
  }

  /**
   * 添加事件监听器
   */
  on<T extends Event>(eventType: string, handler: EventCallback<T>): this {
    if (!this.eventHandlers.has(eventType)) {
      this.eventHandlers.set(eventType, [])
    }
    this.eventHandlers.get(eventType)?.push(handler)
    return this
  }

  /**
   * 鼠标点击事件
   */
  onClick(handler: EventCallback<MouseEvent>): this {
    return this.on('click', handler)
  }

  /**
   * 鼠标悬停事件
   */
  onMouseOver(handler: EventCallback<MouseEvent>): this {
    return this.on('mouseover', handler)
  }

  /**
   * 鼠标离开事件
   */
  onMouseOut(handler: EventCallback<MouseEvent>): this {
    return this.on('mouseout', handler)
  }

  /**
   * 键盘按键事件
   */
  onKeyDown(handler: EventCallback<KeyboardEvent>): this {
    return this.on('keydown', handler)
  }

  /**
   * 更新交互状态
   */
  updateInteractiveState(state: Partial<InteractiveElementState>): this {
    this.state = { ...this.state, ...state }
    return this
  }

  /**
   * 获取交互状态
   */
  getInteractiveState(): InteractiveElementState {
    return { ...this.state }
  }

  // 关联类型
  declare RequestLayoutState: DivRequestLayoutState
  declare PrepaintState: DivPrepaintState
}

/**
 * 创建一个新的Div元素
 */
export function div(): Div & Styled<Div> {
  // 返回带有样式能力的Div元素
  return withStyled(new Div())
}

/**
 * 创建一个具有样式化能力的Div元素
 */
export function styledDiv(): Div & Styled<Div> {
  // 使用withStyled函数创建带样式的Div元素
  return withStyled(new Div())
}

/**
 * 创建一个具有样式化能力的Div元素（辅助函数）
 */
export function createStyledDiv(): Div & Styled<Div> {
  // 明确返回Div & Styled<Div>类型
  const div = new Div()
  const styledDiv = withStyled(div)
  return styledDiv as Div & Styled<Div>
}